using UnityEngine;
using System.Collections;
using UnityEditor;

public class BezierStepNavigator : MonoBehaviour
{
	#region Variables
	
	// Curve
	public	BezierStepNavigator		m_bsnDestination;
	public	float					m_fHandleDistance		=	100.0f;
	public	float					m_fHandleDistanceEnd	=	100.0f;
	public	Bezier					m_bCurve;
	public	bool					m_bCurveIsMoving			= false;
	
	//Speed
	[HideInInspector]
	public	float					m_fBaseSpeedInit;
	public	float					m_fSpeedInit;
	public	float					m_fBaseSpeedEnd;
	[HideInInspector]
	public	float					m_fSpeedEnd;
	private float					m_fSpeedReal;
	public	bool					m_bUseSpeedBlendCrve		= false;
	public	AnimationCurve			m_acSpeedMultCurve			= AnimationCurve.Linear(0.0f, 1.0f, 1.0f, 1.0f);
	
	// Speed related to shape length
	public	bool					m_bUseSpeedShapeCurve		= false;
	public	int						m_iLengthNumSteps			= 50;
	[HideInInspector]
	public	AnimationCurve			m_acSpeedShapeCurve;
	
	// Linking
	public	bool					m_bIsLast					= false;
	public	bool					m_bIsFirst					= false;
	
	// Orienting
	public	bool					m_bOrientForward			= true;
	public	bool					m_bForwardOrientSpecific	= false;
	public	Transform				m_tForwardSpecific;
	public	float					m_fBlendingForwardPercentToComplete	=	0.25f;
	public	AnimationCurve			m_acBlendForwardCurve		= AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 1.0f);
	public	bool					m_bOrientUp					= true;
	public	AnimationCurve			m_acBlendUpCurve			= AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 1.0f);//Linear(0.0f, 0.0f, 1.0f, 1.0f);
	
	#endregion
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	void Awake()
	{
		if(m_bIsFirst)
		{
			Init();
		}
	}
	
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public void Init ()
	{
		m_bCurve = new Bezier(	transform.position
		                      , transform.forward * m_fHandleDistance
		                      , - m_bsnDestination.transform.forward * m_fHandleDistanceEnd
		                      , m_bsnDestination.transform.position);
		
		m_fSpeedInit		=  m_fBaseSpeedInit;
		
		if(!m_bUseSpeedShapeCurve)
		{
			m_fSpeedInit	/=	m_bCurve.Length;
		}
		
		// Init the next one unless it is the last one
		if(!m_bIsLast)
		{
			//m_fSpeedEnd		=	m_fBaseSpeedEnd;
			m_bsnDestination.Init();
		}
		//else
		//{
		//	m_fSpeedEnd		=  m_bsnDestination.m_fSpeedInit;
		//}
		m_fSpeedEnd		=  m_bsnDestination.m_fSpeedInit;
		
		// Fill the speed shape curve if needed
		if(m_bUseSpeedShapeCurve)
		{
			CalculateLengthWithSpeedCurve();
		}
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	private  void CalculateLengthWithSpeedCurve()
	{
		float 		fLength 	=	0;
		Vector3 	vPrev;
		Vector3 	vCur;
		vPrev					=	m_bCurve.GetPointAtTime(0.0f);
		float[]		dafLengths	=	new float[m_iLengthNumSteps];
		Keyframe[] 	kfAllFrames	=	new Keyframe[m_iLengthNumSteps];
		
		// Store the lengths
		for (int i = 1; i < m_iLengthNumSteps + 1; ++i)
		{
			vCur  				=	m_bCurve.GetPointAtTime((float) i / (float) m_iLengthNumSteps);
			dafLengths[i-1]		=	Vector3.Distance(vPrev, vCur);
			fLength		 		+=	dafLengths[i-1];
			vPrev 				=	vCur;
		}
		
		// Create the keyframes
		for (int i = 0; i < m_iLengthNumSteps; ++i)
		{
			kfAllFrames[i]		=	new Keyframe((float)i / (float)m_iLengthNumSteps
			                               		, 1.0f / ((float)m_iLengthNumSteps * dafLengths[i]));
		}
		
		// Create the curve
		m_acSpeedShapeCurve		=	new AnimationCurve(kfAllFrames);
		
		// Smooth the curve
		for (int i = 0; i < m_iLengthNumSteps; ++i)
			m_acSpeedShapeCurve.SmoothTangents(i, 0.0f);
		
		/*
		m_acSpeedShapeCurve		= AnimationCurve.Linear(0.0f, dafLengths[0], 1.0f, dafLengths[m_iLengthNumSteps-1]);
		for (int i = 1; i < m_iLengthNumSteps + 1; ++i)
		{
			if(m_acSpeedShapeCurve.AddKey((float)i / (float)m_iLengthNumSteps, 1.0f / ((float)m_iLengthNumSteps * dafLengths[i-1])) == -1)
			{
				bool fuck = true;
			}
			m_acSpeedShapeCurve.SmoothTangents(i, 0.0f);
		}
		*/
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public void DrawAllCurve()
	{
		// Draw up vector
		Debug.DrawLine(transform.position, transform.position + transform.up * (m_fHandleDistance + m_fHandleDistanceEnd) * 0.5f, Color.blue); 
		
		// Draw this curve step
		m_bCurve.DrawLined();
		
		// Draw the handles
		Debug.DrawLine(transform.position					
		               , transform.position 					+ transform.forward * m_fHandleDistance
		               , Color.green); 
		Debug.DrawLine(m_bsnDestination.transform.position	
		               , m_bsnDestination.transform.position	- m_bsnDestination.transform.forward * m_fHandleDistanceEnd
		               , Color.green);
		
		if(!m_bIsLast)
		{
			m_bsnDestination.DrawAllCurve();
		}
	}
}

